package com.loto.insurance.oem.web.service.common;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.multipart.MultipartFile;

import com.loto.insurance.oem.web.db.mapper.OrderFlowMapper;
import com.loto.insurance.oem.web.db.mapper.OrderInfoExtMapper;
import com.loto.insurance.oem.web.db.mapper.OrderInfoMapper;
import com.loto.insurance.oem.web.db.mapper.OthersMapper;
import com.loto.insurance.oem.web.db.mapper.PolicyFlowMapper;
import com.loto.insurance.oem.web.db.mapper.PolicyInfoAirMapper;
import com.loto.insurance.oem.web.entity.OrderFlow;
import com.loto.insurance.oem.web.entity.OrderInfo;
import com.loto.insurance.oem.web.entity.OrderInfoExt;
import com.loto.insurance.oem.web.entity.PolicyFlow;
import com.loto.insurance.oem.web.entity.PolicyInfoAir;
import com.loto.insurance.oem.web.entity.ProductInfo;
import com.loto.insurance.oem.web.entity.ajax.AirEntity;
import com.loto.insurance.oem.web.entity.ajax.AirJson;
import com.loto.insurance.oem.web.entity.ajax.BaseJson;
import com.loto.insurance.oem.web.entity.config.OEMConfig;
import com.loto.insurance.oem.web.entity.webservice.OrderAir;
import com.loto.insurance.oem.web.enumeration.ConfigFileEnum;
import com.loto.insurance.oem.web.enumeration.ControllerPropertyEnum;
import com.loto.insurance.oem.web.enumeration.InsTypeEnum;
import com.loto.insurance.oem.web.enumeration.OrderStatusEnum;
import com.loto.insurance.oem.web.enumeration.PolicyFeeStatusEnum;
import com.loto.insurance.oem.web.enumeration.PolicyStatusEnum;
import com.loto.insurance.oem.web.utils.Config;
import com.loto.insurance.oem.web.utils.PolicyUtils;
import com.loto.utils.DateUtils;
import com.loto.utils.DecimalUtils;
import com.loto.utils.Http;
import com.loto.utils.XML;

@Service
public class AirIns implements Ins {
  @Autowired
  OrderInfoMapper orderInfoMapper;

  @Autowired
  OrderInfoExtMapper orderInfoExtMapper;

  @Autowired
  PolicyInfoAirMapper policyInfoAirMapper;

  @Autowired
  OrderFlowMapper orderFlowMapper;

  @Autowired
  PolicyFlowMapper policyFlowMapper;

  @Autowired
  OthersMapper othersMapper;

  @Autowired
  DataSourceTransactionManager transactionManager;

  @Autowired
  private DefaultTransactionDefinition def;

  static Logger logger = LogManager.getLogger(AirIns.class);

  @SuppressWarnings("unchecked")
  @Override
  public AirJson parseExcel(MultipartFile file) {
	AirJson airJson = new AirJson();
	HSSFWorkbook wb = null;
	String holderName = "";
	String holderType = "";
	String holderNo = "";
	String holderBirth = "";
	String holderGender = "";
	String insuredName = "";
	String insuredType = "";
	String insuredNo = "";
	String insuredBirth = "";
	String insuredGender = "";
	String insuredTel = "";
	String fromPeriod = "";
	String count = "";
	String flightNo = "";
	String email = "";
	List<AirEntity> list = new ArrayList<AirEntity>();
	try {
	  wb = new HSSFWorkbook(file.getInputStream());

	  HSSFSheet sheet = wb.getSheetAt(0);

	  for (int i = 6; i <= sheet.getLastRowNum(); i++) {
		HSSFRow row = sheet.getRow(i);
		if (row != null && row.getLastCellNum() >= 15) {
		  holderName = row.getCell(10).getStringCellValue() == null ? "" : row
			  .getCell(10).toString();
		  holderType = row.getCell(11).getStringCellValue() == null ? "" : row
			  .getCell(11).toString();
		  holderNo = row.getCell(12).getStringCellValue() == null ? "" : row
			  .getCell(12).toString();
		  holderBirth = 0 != row.getCell(13).getCellType()
			  || !HSSFDateUtil.isCellDateFormatted(row.getCell(13)) ? ""
			  : DateUtils
			      .dateToNormalString(row.getCell(13).getDateCellValue());
		  holderGender = row.getCell(14).getStringCellValue() == null ? ""
			  : row.getCell(14).toString();
		  insuredName = row.getCell(1).getStringCellValue() == null ? "" : row
			  .getCell(1).toString();
		  insuredType = row.getCell(2).getStringCellValue() == null ? "" : row
			  .getCell(2).toString();
		  insuredNo = row.getCell(3).getStringCellValue() == null ? "" : row
			  .getCell(3).toString();
		  insuredBirth = 0 != row.getCell(4).getCellType()
			  || !HSSFDateUtil.isCellDateFormatted(row.getCell(4)) ? ""
			  : DateUtils.dateToNormalString(row.getCell(4).getDateCellValue());
		  insuredGender = row.getCell(5).getStringCellValue() == null ? ""
			  : row.getCell(5).toString();
		  insuredTel = row.getCell(8).getStringCellValue() == null ? "" : row
			  .getCell(8).toString();
		  fromPeriod = 0 != row.getCell(7).getCellType()
			  || !HSSFDateUtil.isCellDateFormatted(row.getCell(7)) ? ""
			  : DateUtils.dateToNormalString(row.getCell(7).getDateCellValue());
		  count = "1";
		  flightNo = row.getCell(6) == null || row.getCell(6) == null ? ""
			  : row.getCell(6).toString();
		  email = row.getCell(9) == null || row.getCell(9) == null ? "" : row
			  .getCell(9).toString();
		  if (!holderName.isEmpty() && !holderType.isEmpty()
			  && !holderNo.isEmpty()
			  && DateUtils.isDate(holderBirth, "yyyy-MM-dd")
			  && !holderGender.isEmpty() && !insuredNo.isEmpty()
			  && !insuredName.isEmpty() && !insuredType.isEmpty()
			  && DateUtils.isDate(insuredBirth, "yyyy-MM-dd")
			  && !insuredGender.isEmpty()
			  && DateUtils.isDate(fromPeriod, "yyyy-MM-dd")
			  && DecimalUtils.isInt(count)) {
			AirEntity entity = new AirEntity();
			entity.setBirth(holderBirth);
			entity.setGender(holderGender);
			entity.setName(holderName);
			entity.setNo(holderNo);
			entity.setType(holderType);
			entity.setPer(fromPeriod);
			entity.setTel(insuredTel);
			entity.setFlight(flightNo);
			entity.setEmail(email);
			entity.setCount(count);
			entity.setBirth1(insuredBirth);
			entity.setGender1(insuredGender);
			entity.setName1(insuredName);
			entity.setNo1(insuredNo);
			entity.setType1(insuredType);
			list.add(entity);
		  }
		}
	  }
	  airJson.setData(list);
	  airJson.setMsg("");
	  airJson.setOk(true);
	} catch (IOException e) {
	  e.printStackTrace();
	  airJson.setMsg(ControllerPropertyEnum.ORDER_INPUT_WRONG.toString());
	  airJson.setOk(false);
	} finally {
	  wb = null;
	}
	return airJson;
  }

  @Override
  public String insertOrder(ProductInfo productInfo, ArrayList<String> arrList,
	  long custId, String custName) {

	long productId = productInfo.getProductId();
	BigDecimal price = productInfo.getProductPrice();
	BigDecimal realPrice = productInfo.getProductRealPrice();
	BigDecimal settlePrice = productInfo.getProductSettlePrice();
	int time = productInfo.getProductTime();
	String timeUnit = productInfo.getProductTimeUnit();
	Calendar now = Calendar.getInstance();
	BigDecimal totalPrice = new BigDecimal("0");
	BigDecimal totalRealPrice = new BigDecimal("0");
	BigDecimal totalSettlePrice = new BigDecimal("0");

	String airHolderName = "";
	String airHolderType = "";
	String airHolderNo = "";
	String airHolderBirth = "";
	String airHolderGender = "";
	String airInsuredName = "";
	String airInsuredType = "";
	String airInsuredNo = "";
	String airInsuredBirth = "";
	String airInsuredGender = "";
	String airInsuredTel = "";
	String airFromPeriod = "";
	String airCount = "";
	String airFlightNo = "";
	String airEmail = "";
	int airHolderAge = 0;
	int airInsuredAge = 0;
	int currentYear = now.get(Calendar.YEAR);
	List<PolicyInfoAir> policyList = new ArrayList<PolicyInfoAir>();

	for (int i = 0; i < arrList.size(); i += 15) {
	  airHolderName = arrList.get(i);
	  airHolderType = arrList.get(i + 1);
	  airHolderNo = arrList.get(i + 2);
	  airHolderBirth = arrList.get(i + 3);
	  airHolderGender = arrList.get(i + 4);

	  airInsuredName = arrList.get(i + 5);
	  airInsuredType = arrList.get(i + 6);
	  airInsuredNo = arrList.get(i + 7);
	  airInsuredBirth = arrList.get(i + 8);
	  airInsuredGender = arrList.get(i + 9);
	  airInsuredTel = arrList.get(i + 10);
	  airFromPeriod = arrList.get(i + 11);
	  airCount = arrList.get(i + 12);
	  airFlightNo = arrList.get(i + 13);
	  airEmail = arrList.get(i + 14);

	  if (!airHolderName.isEmpty() && !airHolderType.isEmpty()
		  && !airHolderNo.isEmpty()
		  && DateUtils.isDate(airHolderBirth, "yyyy-MM-dd")
		  && !airHolderGender.isEmpty() && !airInsuredNo.isEmpty()
		  && !airInsuredName.isEmpty() && !airInsuredType.isEmpty()
		  && DateUtils.isDate(airInsuredBirth, "yyyy-MM-dd")
		  && !airInsuredGender.isEmpty()
		  && DateUtils.isDate(airFromPeriod, "yyyy-MM-dd")
		  && DecimalUtils.isInt(airCount)) {

		airHolderAge = currentYear - DateUtils.getYear(airHolderBirth);
		airInsuredAge = currentYear - DateUtils.getYear(airInsuredBirth);
		if ((airHolderAge > productInfo.getProductAgeMin() || airHolderAge == productInfo
		    .getProductAgeMin())
		    && (airHolderAge < productInfo.getProductAgeMax() || airHolderAge == productInfo
		        .getProductAgeMax())) {
		  if ((airInsuredAge > productInfo.getProductAgeMin() || airInsuredAge == productInfo
			  .getProductAgeMin())
			  && (airInsuredAge < productInfo.getProductAgeMax() || airInsuredAge == productInfo
			      .getProductAgeMax())) {
			if (productInfo.getProductQuota() != 0
			    && Integer.parseInt(airCount) > productInfo.getProductQuota()) {
			  return ControllerPropertyEnum.ORDER_INPUT_QUOTA.toString();
			} else {
			  BigDecimal count = new BigDecimal(airCount);
			  // 准备保单信息
			  PolicyInfoAir policyInfoAir = new PolicyInfoAir();
			  policyInfoAir.setPolicyCustFid(custId);
			  policyInfoAir.setPolicyHolderName(airHolderName);
			  policyInfoAir.setPolicyHolderCredentialType(airHolderType);
			  policyInfoAir.setPolicyHolderCredentialNo(airHolderNo);
			  policyInfoAir.setPolicyHolderGender(airHolderGender);
			  policyInfoAir.setPolicyHolderBirth(DateUtils
				  .parseDate(airHolderBirth));

			  policyInfoAir.setPolicyInsuredName(airInsuredName);
			  policyInfoAir.setPolicyInsuredCredentialType(airInsuredType);
			  policyInfoAir.setPolicyInsuredCredentialNo(airInsuredNo);
			  policyInfoAir.setPolicyInsuredGender(airInsuredGender);
			  policyInfoAir.setPolicyInsuredBirth(DateUtils
				  .parseDate(airInsuredBirth));
			  policyInfoAir.setPolicyInsuredTel(airInsuredTel);
			  policyInfoAir.setPolicyInsuredEmail(airEmail);

			  policyInfoAir.setPolicyFlightNo(airFlightNo);
			  policyInfoAir.setPolicyBegin(DateUtils.parseDate(airFromPeriod));
			  policyInfoAir.setPolicyEnd(PolicyUtils.calulatePolicyEnd(
				  DateUtils.parseDate(airFromPeriod), time, timeUnit));
			  policyInfoAir.setPolicyUnitPrice(price);
			  policyInfoAir.setPolicyRealUnitPrice(realPrice);
			  policyInfoAir.setPolicyCount(Integer.parseInt(airCount));
			  policyInfoAir.setPolicyAmount(count.multiply(price));
			  policyInfoAir.setPolicyRealAmount(count.multiply(realPrice));
			  policyInfoAir.setPolicySettleAmount(count.multiply(settlePrice));
			  policyInfoAir.setPolicyStatusFid(PolicyStatusEnum.UNINSURED
				  .getIndex());
			  policyInfoAir.setPolicyFeeStatusFid(PolicyFeeStatusEnum.UNPAY
				  .getIndex());
			  policyInfoAir
				  .setPolicyOutOrderNo(DateUtils.dateToCompactString(now
				      .getTime()) + othersMapper.getIndex());

			  // policyInfoAir.setPolicyOrderFid(policyOrderFid);

			  policyList.add(policyInfoAir);

			  totalPrice = totalPrice.add(count.multiply(price));
			  totalRealPrice = totalRealPrice.add(count.multiply(realPrice));
			  totalSettlePrice = totalSettlePrice.add(count
				  .multiply(settlePrice));
			}
		  } else {
			return ControllerPropertyEnum.ORDER_INPUT_AGE.toString();
		  }
		} else {
		  return ControllerPropertyEnum.ORDER_INPUT_AGE.toString();
		}
	  } else {
		return ControllerPropertyEnum.ORDER_INPUT_REQUIRED.toString();
	  }
	}

	// 准备订单信息

	String orderName = productInfo.getProductEx() + othersMapper.getIndex();
	OrderInfo orderInfo = new OrderInfo();
	orderInfo.setOrderCustFid(custId);
	orderInfo.setOrderProductFid(productId);
	orderInfo.setOrderProductName(productInfo.getProductName());
	orderInfo.setOrderProductInsName(productInfo.getProductInsName());
	orderInfo.setOrderProductInsFid(productInfo.getProductInsFid());
	orderInfo.setOrderProductTypeFid(productInfo.getProductTypeFid());
	orderInfo.setOrderProductType(productInfo.getProductType());
	orderInfo.setOrderNo(orderName);
	orderInfo.setOrderAmount(totalPrice);
	orderInfo.setOrderSettleAmount(totalSettlePrice);
	orderInfo.setOrderRealAmount(totalRealPrice);
	orderInfo.setOrderRealSettleAmount(totalSettlePrice);
	orderInfo.setOrderStatusFid(OrderStatusEnum.UNPAY.getIndex());
	orderInfo.setOrderPersonCount(arrList.size() / 15);

	orderInfo.setOrderCustName(custName);

	OrderInfoExt orderInfoExt = new OrderInfoExt();
	orderInfoExt.setOrderProductIntro(productInfo.getProductIntro());
	orderInfoExt.setOrderProductOthers(productInfo.getProductOthers());
	orderInfoExt.setOrderProductPic(productInfo.getProductPic());
	orderInfoExt.setOrderProductServeDesc(productInfo.getProductServeDesc());
	orderInfoExt.setOrderProductShortIntro(productInfo.getProductShortIntro());
	orderInfoExt.setOrderProductTimeDesc(productInfo.getProductTimeDesc());

	long orderId = insertAirOrder(policyList, orderInfo, orderInfoExt);
	if (orderId > 0)
	  return String.valueOf(orderId);
	else
	  return ControllerPropertyEnum.ORDER_INPUT_WRONG.toString();
  }

  private long insertAirOrder(List<PolicyInfoAir> policyInfoList,
	  OrderInfo orderInfo, OrderInfoExt orderInfoExt) {
	long orderId = 0;
	TransactionStatus status = transactionManager.getTransaction(def);
	try {
	  // 创建订单信息
	  orderInfoMapper.insertOrder(orderInfo);
	  orderId = orderInfo.getOrderId();

	  orderInfoExt.setOrderId(orderId);
	  orderInfoExtMapper.insertOrderExt(orderInfoExt);
	  // 创建订单流
	  OrderFlow orderFlow = new OrderFlow();
	  orderFlow.setFlowOrderFid(orderId);
	  orderFlow.setFlowOperFid(0);
	  orderFlow.setFlowOrderStatusFid(OrderStatusEnum.UNPAY.getIndex());
	  orderFlow.setFlowOrderStatus(OrderStatusEnum.UNPAY.getName());
	  orderFlow.setFlowMemo(OrderStatusEnum.UNPAY.getDesc());
	  orderFlowMapper.insertOrderFlow(orderFlow);

	  // 创建保单信息
	  for (PolicyInfoAir policyInfo : policyInfoList) {
		policyInfo.setPolicyOrderFid(orderId);
		policyInfoAirMapper.insertPolicyInfo(policyInfo);
		long policyId = policyInfo.getPolicyId();
		if (policyId < 1)
		  throw new RuntimeException();
		// 创建保单流
		PolicyFlow policyFlow = new PolicyFlow();
		policyFlow.setFlowInsTypeFid(InsTypeEnum.AIR.getIndex());
		policyFlow.setFlowPolicyFid(policyId);
		policyFlow.setFlowOperFid(0);
		policyFlow
		    .setFlowPolicyStatusFid(PolicyStatusEnum.UNINSURED.getIndex());
		policyFlow.setFlowPolicyStatus(PolicyStatusEnum.UNINSURED.getName());
		policyFlow.setFlowMemo(PolicyStatusEnum.UNINSURED.getDesc());
		policyFlowMapper.insertPolicyFlow(policyFlow);

	  }

	  transactionManager.commit(status);

	  // TODO 上传至大后台
	  OrderAir orderAir = new OrderAir();
	  orderAir.setOrderInfo(orderInfo);
	  orderAir.setPolicyList(policyInfoList);

	  try {
		String xmlRequest = XML.toXML(orderAir, OrderAir.class);
		logger.info(xmlRequest);
		Map<String, String> paramMap = new HashMap<String, String>();
		paramMap.put("content", xmlRequest);
		paramMap.put("insType",
		    String.valueOf(orderInfo.getOrderProductTypeFid()));
		Config config = new Config();
		OEMConfig configFile = config.getConfigFile(ConfigFileEnum.OEMCONFIG,
		    OEMConfig.class);
		String xmlResponse = Http.doPost(configFile.getOemPlatform()
		    + "/webservice/createorder.service", paramMap);
		logger.info(xmlResponse);
		BaseJson baseJson = XML.fromXML(xmlResponse, BaseJson.class);
		if (baseJson != null && baseJson.isOk()) {
		  // 更新order的platform
		  Map<String, Object> params = new HashMap<String, Object>();
		  params.put("orderId", orderId);
		  params.put("orderPlatformId", baseJson.getMsg());
		  orderInfoMapper.updateOrderPlatformById(params);
		}
	  } catch (Exception e) {
		e.printStackTrace();
	  }

	} catch (Exception ex) {
	  transactionManager.rollback(status);
	  orderId = 0;
	}
	return orderId;
  }
}
